#ifndef _THREAD_POOL_
#define _THREAD_POOL_

// 线程池
#include "Thread.hpp"
#include "Mutex.hpp"
#include "log.hpp"
#include <unistd.h>
#include <queue>
#include <iostream>

const int threadDefaultNum = 4;  // 默认线程池的线程个数

template<class T>
class ThreadPool
{
public:
    T popTask()
    {
        T task = _task.front();
        _task.pop();
        return task;
    }

    Mutex* outMutxObj()
    {
        return &_mtx;
    }

    bool taskEmpty()
    {
        return _task.empty();
    }

    void CondWait()
    {
        // 条件变量等待
        pthread_cond_wait(&_cond, &_mtx._mtx);
    }

public:
    ThreadPool(ThreadPool<T>&) = delete;
    ThreadPool<T> operator=(ThreadPool<T>&) = delete;

    static ThreadPool<T>* getThreadPoolObject(int threadNum = threadDefaultNum)
    {
        if (_object == nullptr)
        {
            MutexGuardian mtx(mtx_);
            if (_object == nullptr) _object = new ThreadPool<T>(threadNum);
        }
        return _object;
    }

    void run()
    {
        // 线程池启动函数 全体线程启动起来，准备分配任务进行执行
        for (int i = 0; i < _threadNum; ++i) _thread[i]->start();
    }

    static void* routine(void* args)  // 静态方法，这样参数里才可以不出现this指针
    {
        ThreadData* td = (ThreadData*)args;
        ThreadPool<T>* tp = (ThreadPool<T>*)(td->_args);
        T task;
        while (true)
        {
            {
                MutexGuardian mtx(tp->outMutxObj());  // 上锁
                while (tp->taskEmpty()) tp->CondWait();  // 等待
                task = tp->popTask();
            }
            // std::cout << td->_name << "执行任务:" << task._x << task._type << task._y << "=" << task() << std::endl;  // 执行任务
            task();
            // logMessage(NORMAL, "%s 执行任务: %d%c%d=%d", td->_name.c_str(), task._x, task._type, task._y, task());
        }

        return nullptr;
    }

    void pushTask(T task)
    {
        MutexGuardian mtx(&_mtx);  // 上锁
        _task.push(task);
        pthread_cond_signal(&_cond);  // 发信号
    }

    ~ThreadPool()
    {
        pthread_cond_destroy(&_cond);
        for (int i = 0; i < _threadNum; ++i)
        {
            _thread[i]->join();
        }

        delete mtx_;
    }
private:
    ThreadPool(int threadNum):_threadNum(threadNum)
    {
        pthread_cond_init(&_cond, nullptr);  // 初始化条件变量
        for (int i = 1; i <= threadNum; ++i)
        {
            _thread.push_back(new Thread(i, routine, this));
        }
    }

    std::vector<Thread*> _thread;  // 线程池 封装线程类型，便于创建线程 321中2个角色中的消费者
    std::queue<T> _task;           // 任务缓冲区 321中的1个场景
    int _threadNum;                // 线程池中的线程个数
    Mutex _mtx;                    // 一把互斥锁即可 自定义的互斥锁对象
    pthread_cond_t _cond;          // 条件变量，用户同步线程和派发任务

    static ThreadPool<T>* _object;  // 单例模式，这里存储着当前进程关于此类型的唯一对象
    static Mutex* mtx_;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::_object = nullptr;

template<class T>
Mutex* ThreadPool<T>::mtx_ = new Mutex;

#endif